import paho.mqtt.client as mqtt
import random
import time
import json

# MQTT 配置
broker_address = "39.108.140.19"  # 服务器地址
port = 1883  # 端口

# 设备信息
tenant_code = "inspur"
temperatureSensor = {
    "device_code": "TemperatureSensor_1",
    "client_id": "inspur:TemperatureSensor_1:d09e62454680dcce150da006cf43306601a69f6b",
    "username": "TemperatureSensor_1zVPPdCY1",
    "password": "U47qET~JAGbqIjp."
}
smokeDetector = {
    "device_code": "SmokeDetector_1",
    "client_id": "inspur:SmokeDetector_1:b9d8cf38250b098ff2d891fef55a548f4b2b1bc0",
    "username": "SmokeDetector_11ape74YZ",
    "password": "leX4igDPR$UrM.o%"
}
gasSensor = {
    "device_code": "GasDetectionSensor_1",
    "client_id": "inspur:GasDetectionSensor_1:0827cdb14ff99922f4c1ad3d89ae4ea1d1a028a5",
    "username": "GasDetectionSensor_1LxHX2bJd",
    "password": "D2hXrE^RfKiWLXR?"
}


# 初始化MQTT客户端
def init_mqtt_client(device_code, client_id, username, password):
    # 连接回调
    def on_connect(client, userdata, flags, rc):
        if rc == 0:
            print(f"{device_code} has connected to inspur successfully!")
        else:
            print(f"{device_code} failed to connect, return code %d\n", rc)

    #   订阅回调
    def on_subscribe(client, userdata, mid, granted_qos):
        print("On Subscribed: qos = %d" % granted_qos)

    #   取消订阅回调
    def on_unsubscribe(client, userdata, mid):
        print("On unSubscribed: qos = %d" % mid)

    #   发布消息回调
    def on_publish(client, userdata, mid):
        print("On onPublish: qos = %d" % mid)

    #   断开链接回调
    def on_disconnect(client, userdata, rc):
        print(f"{device_code} disconnection rc = " + str(rc))

    client_mqtt = mqtt.Client(client_id=client_id)
    client_mqtt.username_pw_set(username=username, password=password)
    client_mqtt.on_connect = on_connect
    client_mqtt.on_subscribe = on_subscribe
    client_mqtt.on_unsubscribe = on_unsubscribe
    client_mqtt.on_publish = on_publish
    client_mqtt.on_disconnect = on_disconnect

    # 连接到MQTT服务器
    client_mqtt.connect(broker_address, port=port)

    return client_mqtt

# 模拟设备数据生成函数
def generate_device_data(device_type):
    is_abnormal = random.random() < 0.1  # 10% 概率生成异常数据
    if is_abnormal:
        print(f'{device_type}异常数据')

    if device_type == "temperature":
        return generate_temperature_data(is_abnormal)
    elif device_type == "smoke":
        return generate_smoke_data(is_abnormal)
    elif device_type == "gas":
        return generate_gas_data(is_abnormal)


def generate_temperature_data(is_abnormal=False):
    # 定义温度传感器的阈值和范围
    TEMPERATURE_RANGE = (15.0, 45.0)  # 正常温度范围：15.0°C 到 45.0°C
    ABSOLUTE_HUMIDITY_RANGE = (5.0, 20.0)  # 正常绝对湿度范围：5.0 g/m³ 到 20.0 g/m³
    AIR_PRESSURE_RANGE = (950.0, 1050.0)  # 正常气压范围：950 hPa 到 1050 hPa
    EQUIPMENT_POWER_RANGE = (30.0, 100.0)  # 正常电池电量范围：30% 到 100%
    SIGNAL_STRENGTH_RANGE = (-70.0, -30.0)  # 正常信号强度范围：-70 dBm 到 -30 dBm
    STATUS_OPTIONS = [0, 1, 2]  # 正常0/故障1/低电量2

    if is_abnormal:
        # 如果是异常数据，随机生成超出阈值的异常数据
        temperature = random.uniform(10.0, 50.0)  # 超出温度范围的值
        absolute_humidity = random.uniform(3.0, 25.0)  # 超出湿度范围的值
        air_pressure = int(random.uniform(900.0, 1100.0))  # 超出气压范围的值
        equipment_power = int(random.uniform(0.0, 15.0))  # 低于电池电量阈值的值
        signal_strength = int(random.uniform(-90.0, -20.0))  # 弱信号或异常强信号
        status = random.choice([1, 2])  # 异常状态
    else:
        # 正常数据
        temperature = round(random.uniform(TEMPERATURE_RANGE[0], TEMPERATURE_RANGE[1]), 2)
        absolute_humidity = round(random.uniform(ABSOLUTE_HUMIDITY_RANGE[0], ABSOLUTE_HUMIDITY_RANGE[1]), 2)
        air_pressure = int(random.uniform(AIR_PRESSURE_RANGE[0], AIR_PRESSURE_RANGE[1]))
        equipment_power = int(random.uniform(EQUIPMENT_POWER_RANGE[0], EQUIPMENT_POWER_RANGE[1]))
        signal_strength = int(random.uniform(SIGNAL_STRENGTH_RANGE[0], SIGNAL_STRENGTH_RANGE[1]))
        status = 0  # 正常状态
    return {
        "Temperature": temperature,
        "AbsoluteHumidity": absolute_humidity,
        "AirPressure": air_pressure,
        "EquipmentPower": equipment_power,
        "SignalStrength": signal_strength,
        "Status": status
    }


def generate_smoke_data(is_abnormal=False):
    # 定义烟感器的阈值和范围
    VOLTAGE_RANGE = (342.0, 418.0)  # 正常电压范围：180 V 到 240 V
    FORWARD_ACTIVE_POWER_RANGE = (900.0, 1100.0)  # 正常正向有功总电量范围：0.0 kWh 到 500.0 kWh
    TOTAL_POSITIVE_REACTIVE_POWER_RANGE = (720.0, 880.0)  # 正常正向无功总电量范围：0.0 kVarh 到 200.0 kVarh
    REVERSE_ACTIVE_POWER_RANGE = (0.0, 100.0)  # 正常反向有功总电量范围：0.0 kWh 到 100.0 kWh
    REVERSE_REACTIVE_POWER_RANGE = (0.0, 100.0)  # 正常反向无功总电量范围：0.0 kVarh 到 100.0 kVarh
    SMOKE_SCOPE_RANGE = (0.0, 100.0)  # 正常烟雾浓度范围：0 ppm 到 100 ppm
    EQUIPMENT_POWER_RANGE = (30.0, 100.0)  # 正常电池电量范围：30% 到 100%
    SIGNAL_STRENGTH_RANGE = (-70.0, -30.0)  # 正常信号强度范围：-70 dBm 到 -30 dBm
    STATUS_OPTIONS = [0, 1, 2]  # 正常0/故障1/低电量2

    if is_abnormal:
        # 如果是异常数据，随机生成超出阈值的异常数据
        voltageA = round(random.uniform(332.0, 428.0),2)  # 超出电压范围的值
        voltageB = round(random.uniform(332.0, 428.0),2)  # 超出电压范围的值
        voltageC = round(random.uniform(332.0, 428.0),2)  # 超出电压范围的值
        forwardActiveTotalPower = random.uniform(-10.0, 600.0)  # 超出电量范围的值
        totalPositiveReactivePower = random.uniform(-10.0, 300.0)  # 超出无功电量范围的值
        reverseTotalActivePower = random.uniform(-10.0, 150.0)  # 超出反向电量范围的值
        reverseTotalReactivePower = random.uniform(-10.0, 150.0)  # 超出反向无功电量范围的值
        smokeScope = int(random.uniform(-10.0, 200.0))  # 超出烟雾浓度范围的值
        equipment_power = int(random.uniform(0.0, 15.0))  # 低于电池电量阈值的值
        signal_strength = int(random.uniform(-90.0, -20.0))  # 弱信号或异常强信号
        status = random.choice([1, 2])  # 异常状态
    else:
        # 正常数据
        voltageA = round(random.uniform(VOLTAGE_RANGE[0], VOLTAGE_RANGE[1]), 2)
        voltageB = round(random.uniform(VOLTAGE_RANGE[0], VOLTAGE_RANGE[1]), 2)
        voltageC = round(random.uniform(VOLTAGE_RANGE[0], VOLTAGE_RANGE[1]), 2)
        forwardActiveTotalPower = round(random.uniform(FORWARD_ACTIVE_POWER_RANGE[0], FORWARD_ACTIVE_POWER_RANGE[1]), 2)
        totalPositiveReactivePower = round(
            random.uniform(TOTAL_POSITIVE_REACTIVE_POWER_RANGE[0], TOTAL_POSITIVE_REACTIVE_POWER_RANGE[1]), 2)
        reverseTotalActivePower = round(random.uniform(REVERSE_ACTIVE_POWER_RANGE[0], REVERSE_ACTIVE_POWER_RANGE[1]), 2)
        reverseTotalReactivePower = round(
            random.uniform(REVERSE_REACTIVE_POWER_RANGE[0], REVERSE_REACTIVE_POWER_RANGE[1]), 2)
        smokeScope = int(random.uniform(SMOKE_SCOPE_RANGE[0], SMOKE_SCOPE_RANGE[1]))
        equipment_power = int(random.uniform(EQUIPMENT_POWER_RANGE[0], EQUIPMENT_POWER_RANGE[1]))
        signal_strength = int(random.uniform(SIGNAL_STRENGTH_RANGE[0], SIGNAL_STRENGTH_RANGE[1]))
        status = 0  # 正常状态

    return {
        "voltageA": voltageA,
        "voltageB": voltageB,
        "voltageC": voltageC,
        "forwardActiveTotalPower": forwardActiveTotalPower,
        "totalPositiveReactivePower": totalPositiveReactivePower,
        "reverseTotalActivePower": reverseTotalActivePower,
        "reverseTotalReactivePower": reverseTotalReactivePower,
        "SmokeScope": smokeScope,
        "EquipmentPower": equipment_power,
        "SignalStrength": signal_strength,
        "Status": status
    }


def generate_gas_data(is_abnormal=False):
    # 定义瓦斯监测传感器的阈值和范围
    GAS_DENSITY_RANGE = (0.0, 500.0)  # 正常瓦斯浓度范围：0 ppm 到 500 ppm
    SMOKE_SCOPE_RANGE = (0.0, 100.0)  # 正常烟雾浓度范围：0 ppm 到 100 ppm
    GAS_TYPES = ["Methane", "CarbonMonoxide", "Oxygen", "Nitrogen", "Hydrogen"]
    EQUIPMENT_POWER_RANGE = (30.0, 100.0)  # 正常电池电量范围：30% 到 100%
    SIGNAL_STRENGTH_RANGE = (-70.0, -30.0)  # 正常信号强度范围：-70 dBm 到 -30 dBm
    STATUS_OPTIONS = [0, 1, 2]  # 正常0/故障1/低电量2

    if is_abnormal:
        # 如果是异常数据，随机生成超出阈值的异常数据
        gasDensity = random.uniform(-10.0, 1000.0)  # 超出瓦斯浓度范围的值
        smokeScope = random.uniform(-10.0, 200.0)  # 超出烟雾浓度范围的值
        gasType = "Methane"
        equipment_power = int(random.uniform(0.0, 15.0))  # 低于电池电量阈值的值
        signal_strength = int(random.uniform(-90.0, -20.0))  # 弱信号或异常强信号
        status = random.choice([1, 2])  # 异常状态
    else:
        # 正常数据
        gasDensity = round(random.uniform(GAS_DENSITY_RANGE[0], GAS_DENSITY_RANGE[1]), 2)
        smokeScope = round(random.uniform(SMOKE_SCOPE_RANGE[0], SMOKE_SCOPE_RANGE[1]), 2)
        gasType = "Methane"
        equipment_power = int(random.uniform(EQUIPMENT_POWER_RANGE[0], EQUIPMENT_POWER_RANGE[1]))
        signal_strength = int(random.uniform(SIGNAL_STRENGTH_RANGE[0], SIGNAL_STRENGTH_RANGE[1]))
        status = 0  # 正常状态

    return {
        "GasDensity": gasDensity,
        "SmokeScope": smokeScope,
        "GasType": gasType,
        "EquipmentPower": equipment_power,
        "SignalStrength": signal_strength,
        "Status": status
    }

# 发布设备数据的函数
def publish_device_data(client, device_code, device_type):
    data = {
        "data": generate_device_data(device_type),
        "timestamp": int(time.time())
    }
    topic = f"device/{tenant_code}/{device_code}/report"
    payload = json.dumps(data)
    client.publish(topic, payload=payload)
    print(f"Published to {topic}: {payload}")


if __name__ == '__main__':
    # 温度传感器1号
    temperatureClient = init_mqtt_client(temperatureSensor['device_code'], temperatureSensor['client_id'], temperatureSensor['username'], temperatureSensor['password'])

    # 烟感器1号
    smokeClient = init_mqtt_client(smokeDetector['device_code'], smokeDetector['client_id'], smokeDetector['username'], smokeDetector['password'])

    # 瓦斯检测传感器1号
    gasClient = init_mqtt_client(gasSensor['device_code'], gasSensor['client_id'], gasSensor['username'], gasSensor['password'])

    temperatureClient.loop_start()
    smokeClient.loop_start()
    gasClient.loop_start()

    try:
        while True:
            # 发布温度传感器数据
            publish_device_data(temperatureClient, temperatureSensor['device_code'], "temperature")

            # 发布烟感器数据
            publish_device_data(smokeClient, smokeDetector['device_code'], "smoke")

            # 发布瓦斯检测传感器数据
            publish_device_data(gasClient, gasSensor['device_code'], "gas")

            time.sleep(10)

    except KeyboardInterrupt:
        print("Exiting...")

    finally:
        temperatureClient.loop_stop()
        temperatureClient.disconnect()
        smokeClient.loop_stop()
        smokeClient.disconnect()
        gasClient.loop_stop()
        gasClient.disconnect()
